<template>
  <div class="c-form">
    <el-form ref="cform" :model="form" :label-width="option.labelWidth">
      <el-form-item v-for="(item,index) in option.items" :key="index"
                    v-show="!item.hide"
                    :label="item.label"
                    :prop="item.key"
                    :rules="item.rules?item.rules:[{required:false}]"
                    :style="item.style||'width:50%;'">
        <template v-if="item.type==='select'">
          <el-select v-model="form[item.key]" 
                     filterable
                     :allow-create='item.isCreate'
                     :default-first-option='item.isEnterSure'
                     :clearable='item.clearable'
                     :disabled='item.disabled'
                     :placeholder="item.placeholder"
                     :filter-method="item.isDefaultQuery?initialQuery:()=>{}"
                     @visible-change="visibleChange($event,{item,index})"
                     @focus="focus($event,{item,index})"
                     @blur="blur($event,{item,index})">
            <el-option
              v-for="li in cacheData.flag.refleshDicData?getDicData({item,index}):getDicData({item,index})"
              :key="li['dataCode']"
              :label="li['dataText']"
              :value="li['dataCode']">
            </el-option>
          </el-select>
        </template>
        <template v-else-if="item.type==='date'">
          <el-date-picker
            v-model='form[item.key]'
            :align='item.align'
            type="date"
            :clearable='item.clearable'
            :placeholder='item.placeholder'
            :picker-options='item.pickerOptions'>
          </el-date-picker>
        </template>
        <template v-else-if="item.type==='dates'">
          <el-date-picker
            v-model='form[item.key]'
            :align='item.align'
            type="daterange"
            :clearable='item.clearable'
            range-separator="至"
            start-placeholder="起始日期"
            end-placeholder="结束日期"
            :picker-options='item.pickerOptions'>
          </el-date-picker>
        </template>
        <template v-else-if="item.type==='time'">
          <el-date-picker
            v-model="form[item.key]"
            type="datetime"
            :placeholder='item.placeholder'
            :align='item.align'
            :clearable='item.clearable'
            :picker-options='item.pickerOptions'>
          </el-date-picker>
        </template>
        <template v-else-if="item.type==='times'">
          <el-date-picker
            v-model="form[item.key]"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            :align='item.align'
            :clearable='item.clearable'
            :picker-options='item.pickerOptions'>
          </el-date-picker>
        </template>
        <template v-else-if="item.type==='slot'">
          <slot :name="item.slotName"/>
        </template>
        <template v-else-if="item.type==='slotText'">
          <div>{{item.text}}</div>
        </template>
        <template v-else-if="item.type==='img'">
          <div v-if="cacheData.imgs[item.key]||cacheData.viewImgs[item.key]" style="position:relative;width:100px;height:100px;margin-bottom:10px;">
            <div v-if="cacheData.imgs[item.key]" class="el-icon-close" style="position:absolute;top:0;right:0;width:20px;height:20px;background:skyblue;text-align: center;line-height: 20px;cursor:pointer;" @click="removeImg(item)"></div>
            <img :src="cacheData.imgs[item.key]||cacheData.viewImgs[item.key]" style="width:100%;height:100%;">
          </div>
          <div v-else>暂无图片</div>
          <el-button @click="_uploadImg(item,index)">点击上传</el-button>
        </template>
        <template v-else-if="item.type==='radio'">
          <el-radio-group v-model="form[item.key]">
            <el-radio v-for="li in cacheData.flag.refleshDicData?getDicData({item,index}):getDicData({item,index})"
                      :key="li['dataCode']"
                      :label="li['dataCode']">{{li['dataText']}}</el-radio>
          </el-radio-group>
        </template>
        <template v-else-if="item.type==='switch'">
          <el-switch
            v-model="form[item.key]"
            :disabled="item.disabled"
            :active-text="item.activeText"
            :inactive-text="item.inActiveText"
            :active-value="item.activeValue"
            :inactive-value="item.inactiveValue">
          </el-switch>
        </template>
        <template v-else-if="item.type==='checkbox'">
          <el-checkbox-group v-model="form[item.key]">
            <el-checkbox v-for="li in cacheData.flag.refleshDicData?getDicData({item,index}):getDicData({item,index})"
                         :key="li['dataCode']"
                         :label="li['dataCode']">{{li['dataText']}}</el-checkbox>
          </el-checkbox-group>
        </template>
        <template v-else-if="item.type==='cnumber'">
          <el-input v-model='form[item.key]'
                    type='text'
                    :placeholder='item.placeholder'
                    :maxlength='item.maxLength'
                    :show-word-limit='item.isCount'
                    :disabled='item.disabled'
                    :readonly='item.readonly'
                    :clearable='item.clearable'></el-input>
        </template>
        <template v-else>
          <el-input v-model='form[item.key]'
                    :type='item.type'
                    :placeholder='item.placeholder'
                    :maxlength='item.maxLength'
                    :show-word-limit='item.isCount'
                    :disabled='item.disabled'
                    :readonly='item.readonly'
                    :clearable='item.clearable'
                    :autosize='item.autosize'></el-input>
        </template>
      </el-form-item>

      <!-- <el-button @click="test">测 试</el-button> -->

      <el-form-item style="width:100%;text-align:right;" :style="option.submitBtn||option.reBackBtn?'':'margin-bottom:0'">
        <el-button v-if="option.reBackBtn" @click="reBack">重 置</el-button>
        <el-button v-if="option.submitBtn" type="primary" @click="onSubmit">提 交</el-button>
      </el-form-item>
    </el-form>
    <input v-show="false" ref="uploadImg" type="file" accept="image/*" @change="uploadImg"/>
  </div>
</template>

<script>
export default {
  props:{
    //表单配置项信息
    option:{
      type:Object,
    },
    //绑定的data,会动态修改form值
    data:{
      type:Object
    },
    //初始化的数据
    initData:{
      type:Object
    },
  },
  data() {
    return {
      form: {
      },
      //存放字典值的对象
      dicData:{
      },
      //存放一些缓存数据
      cacheData:{
        currentSelect:{},
        flag:{
          refleshDicData:false,
        },
        currentUploadImg:{
          item:{},
          index:'',
        },
        //存放上传的图片
        imgs:{},
        //存放展示的图片
        viewImgs:{},
      },
    }
  },
  created(){
    this.init()
  },
  watch:{
    'form':{
      handler(n){
        this.$emit('change',this.formatterForm(n))
      },
      deep:true
    },
    'data':{
      handler(n){
        this.formtterData(n,this.form)
      },
      deep:true
    },
    'cacheData.imgs':{
      handler(){
        this.$emit('change',this.formatterForm(this.form))
      },
      deep:true
    },
  },
  methods: {
    //移除图片
    removeImg({key}){
      this.$confirm(`是否移除已上传的图片?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.cacheData.imgs[key]=''
        this.form[key]=''
        this.$message({
          type: 'success',
          message: '已移除'
        });
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '操作已取消'
        });          
      });
    },
    //上传单图片按钮事件
    _uploadImg(item,index){
      this.cacheData.currentUploadImg={item,index}
      this.$refs.uploadImg.click()
    },
    //原生上传事件
    uploadImg(event){
      let data = this.$refs.uploadImg.files[0];
      try{
        let imgFile = new FileReader();
        let _this=this
        imgFile.readAsDataURL(data);
        imgFile.onload = res => {
          let result=res.target.result
          let { currentUploadImg } = _this.cacheData
          let { key } = currentUploadImg.item
          _this.cacheData.imgs[key]=result
        }
      }catch(e){
        console.log(e)
      }
    },
    clearValidate(){
      if(this.$refs['cform']){
        this.$refs['cform'].clearValidate()
      }
    },
    init(){
      this.initForm()
      this.initDicData()
      this.watchItems()
      this.setOptionCacheData()
      this.setViewImgs()
      this.$nextTick(()=>{
        this.clearValidate()
      })
    },
    onSubmit() {
      this.$refs['cform'].validate((valid) => {
        if (valid) {
          this.$emit('submit',this.formatterForm(this.form))
        } else {
          console.log('error submit!!');
          return false;
        }
      })
    },
    reBack(){
      this.initForm()
      this.setOptionCacheData()
    },

    //在option找到key对应的索引
    findOptionByKey(key){
      let index=-1
      for(let i=0;i<this.option.items.length;i++){
        let opKey=this.option.items[i].key
        if(opKey===key){
          index=i
          break
        }
        //如果是dates或times之类有多个变量的
        if(opKey.indexOf('|')!=-1){
          let key1=opKey.split('|')[0]
          let key2=opKey.split('|')[1]
          if(key1===key||key2===key){
            index=i
            break
          }
        }
      }
      return index
    },
  
    //初始化表单
    initForm(){
      this.formtterData(this.initData)

      let _this=this
      this.$nextTick(function(){
        _this.$refs['cform'].validate(valid=>valid)
      })
    },
    //初始化字典值
    initDicData(){
      let dicDatasStr=sessionStorage.getItem('s-dictionary')||'{"content":{}}'
      let dicDatas=JSON.parse(dicDatasStr)
      this.dicData=dicDatas.content
      this.setOptionDicData()
    },
    // 设置观赏图片
    setViewImgs(){
      this.cacheData.viewImgs={}
      for(let key in this.initData){
        let index=this.findOptionByKey(key)
        if(index===-1){ 
          continue
        }
        let { type } =this.option.items[index]
        if(type==='img'){//图片类型
          this.cacheData.viewImgs[key]=this.initData[key]
        }
      }
    },
    //设置option的img
    setOptionCacheData(){
      this.cacheData.imgs={}
      let { items } = this.option
      let tmpObj={}
      for(let i=0;i<items.length;i++){
        let item=items[i]
        if(item.type==='img'){
          tmpObj[item.key]=''
        }
      }
      this.cacheData.imgs=Object.assign(tmpObj,this.cacheData.imgs)
    },
    //重设option传来的dicData值
    setOptionDicData(){
      let { items } = this.option
      for(let i=0;i<items.length;i++){
        let item=items[i]
        if((item.type==='select'||item.type==='radio'||item.type==='checkbox')&&!item.dicKey){
          this.dicData[item.key]=item.dicDatas.map(el=>{
            return {
              dataText:el[item.optionLabel||'dataText'],
              dataCode:el[item.optionVal||'dataCode'],
              dataTextAbbr:el[item.optionAbbr||'dataTextAbbr']||''
            }
          })
        }
      }
    },
    //为表单中元素注册watch监听
    watchItems(){
      let { items }=this.option
      for(let i=0;i<items.length;i++){
        let current=items[i]
        let { watch=null,key,type }=current
        if(type==='cnumber'){
          this.$watch('form.'+key,function(...rests){
            let newVal=rests[0]
            let o=rests[1]
            if(newVal){
              let n=''
              if(newVal[0]==='-'){
                n=newVal.slice(1)
              }else{
                n=newVal
              }
              if(n){
                if(isNaN(n[n.length-1])&&n[n.length-1]!='.'){
                  this.form[key]=o
                  return
                }else{
                  let index=n.indexOf('.')
                  if(index!=-1){
                    //不能出现多个.
                    if(n.indexOf('.',index+1)!=-1){
                      this.form[key]=o
                      return
                    }else{
                      let tmpArr=n.split('.')
                      let a=tmpArr[0]
                      let b=tmpArr[1]
                      for(let i=0;i<a.length;i++){
                        if(isNaN(a[i])){
                          this.form[key]=o
                          return
                        }
                      }
                      for(let i=0;i<b.length;i++){
                        if(isNaN(b[i])){
                          this.form[key]=o
                          return
                        }
                      }
                    }
                  }else{//如果不是小数，则不允许出现非数字
                    for(let i=0;i<n.length;i++){
                      if(isNaN(n[i])){
                        this.form[key]=o
                        return
                      }
                    }
                  }
                }
              }
              //如果是负号开头
              if(n&&n!=newVal){
                if(isNaN(n[0])){
                  this.form[key]=o
                  return
                }
              }
              //如果是0打头,第二位开
              if(n&&n[0]==0){
                if(n[1]&&n[1]==0){
                  this.form[key]=o
                  return
                }
              }
            }
          })
        }
        if(type==='img'){
          this.$watch('form.'+key,//校验图片
            function(){
              this.$refs['cform'].validateField(key)
            }
          )
        }
        if(watch){
          this.$watch('form.'+key,watch)
        }
      }
    },
    //将传入数据格式化为表单数据
    formtterData(data,form={}){
      let tmpObj={}
      for(let prop in data){
        let index=this.findOptionByKey(prop)
        if(index===-1){
          //说明是未在option.items中配置的值,直接传给data
          tmpObj[prop]=data[prop] 
          continue
        }
        let { type,key }=this.option.items[index]
        if(type==='text'||type==='textarea'||type==='select'||type==='slot'||type==='radio'||type==='switch'||type==='checkbox'||type==='img'){
          tmpObj[key]=data[prop]
        }else if(type==='cnumber'){
          tmpObj[key]=data[prop]
        }else if(type==='date'||type==='time'){
          tmpObj[key]=new Date(data[prop])
        }else if(type==='dates'||type==='times'){
          let key1=key.split('|')[0]
          let key2=key.split('|')[1]
          let val1=data[key1]?new Date(data[key1]):''
          let val2=data[key2]?new Date(data[key2]):''
          tmpObj[key]=[val1,val2]
        }
      }
      for(let i=0;i<this.option.items.length;i++){
        let el=this.option.items[i]
        let { key,type } =el
        if(type==='img'){
          if(data[key]){
            tmpObj[key]=this.cacheData.viewImgs[key]===data[key]?'':data[key]
          }else{
            tmpObj[key]=''
          }
        }
      }
      let tmpStrA=JSON.stringify(this.form)
      let tmpStrB=JSON.stringify(tmpObj)
      if(tmpStrA!=tmpStrB){
        this.form=Object.assign(form,tmpObj)
      }
      console.log('form')
      console.log(this.form)
    },
    //格式化表单,将当前表单数据格式化为传出数据
    formatterForm(data){
      let tmpObj={}
      let form={}
      let imgs=this.cacheData.imgs
      for(let key in data){
        let index=this.findOptionByKey(key)
        let value=data[key]
        if(index===-1){
          /**
           * 说明是未在option.items中配置的值
           */
          tmpObj[key]=value
          continue
        }
        let { type }=this.option.items[index]
        if(type==='text'||type==='textarea'||type==='select'||type==='slot'||type==='radio'||type==='switch'||type==='checkbox'){
          tmpObj[key]=value
        }else if(type==='cnumber'){
          tmpObj[key]=value
        }else if(type==='date'){
          tmpObj[key]=this.formatDate(value)
        }else if(type==='dates'){
          let key1=key.split('|')[0]
          let key2=key.split('|')[1]
          tmpObj[key1]=this.formatDate(value?value[0]:'')
          tmpObj[key2]=this.formatDate(value?value[1]:'')
        }else if(type==='time'){
          tmpObj[key]=this.formatTime(value)
        }else if(type==='times'){
          let key1=key.split('|')[0]
          let key2=key.split('|')[1]
          tmpObj[key1]=this.formatTime(value?value[0]:'')
          tmpObj[key2]=this.formatTime(value?value[1]:'')
        }else if(type==='img'){
          if(this.cacheData.imgs[key]){
            tmpObj[key]=this.cacheData.imgs[key]
          }else if(this.cacheData.viewImgs[key]===value){
            tmpObj[key]=""
          }else{
            tmpObj[key]=value
          }
        }
      }
      for(let key in imgs){
        if(imgs[key]){
          tmpObj[key]=imgs[key]
        }
      }
      form=Object.assign(tmpObj,form)
      return form
    },

    //焦点事件
    focus(e,item){
      this.cacheData.currentSelect=item
    },
    //失焦事件
    blur(e,item){
      this.cacheData.currentSelect={}
    },
    //选择框下拉栏显隐事件
    visibleChange(type,{item}){
      if(!type&&item.isDefaultQuery){
        this.initDicData()
      }
    },
    //返回dicData
    getDicData({index,item}){
      if(item.dicKey){
        return this.dicData[item.dicKey]||[]
      }else{
        return this.dicData[item.key]||[]
      }
    },
    //设置dicData
    setDicData({index,item},newVal){
      let dicData=JSON.parse(JSON.stringify(newVal))
      if(item.dicKey){
        this.dicData[item.dicKey]=dicData
      }else{
        this.dicData[item.key]=dicData
      }
    },
    //首字母查询
    initialQuery(val){

      let currentSelect=this.cacheData.currentSelect
      let result = []
      let dicData=this.getDicData(currentSelect)
      let copyDicData=dicData
      if (val) {
        
        dicData.map(function (currentValue) {
          if (currentValue['dataText'].search(val) != -1) {//排头查询
            result.push(currentValue)
          } else {
            if(currentValue['dataTextAbbr']){
              let keys = currentValue['dataTextAbbr'].split(',');
              keys.map(function (current) {
                if (current === val) {
                  result.push(currentValue)
                }
              })
            }
          }
        })
        //搜索到相应的数据就把符合条件的n个数据赋值copyDicData
        if (result.length) {
          dicData = result
        } else {
          dicData = copyDicData
        }
      } else {
        //没有搜索到数据，就还展示所有的copyDicData
        dicData = copyDicData
      }
      this.setDicData(currentSelect,dicData)
      this.cacheData.flag.refleshDicData=!this.cacheData.flag.refleshDicData
    },
    // 格式转换,时间类
    // 日期格式转换,时间对象转yyyy-mm-dd
    formatDate(datetime){
      if(!datetime){
        return ''
      }
      let year = datetime.getFullYear()
      let month = datetime.getMonth()+1
      let date = datetime.getDate()

      if(month<10){
        month = "0" + month
      }
      if(date<10){
        date = "0" + date
      }
      return year + '-' + month + '-' + date
    },
    //对不符合标准的补零
    formatZero(x){
      return x<10?("0"+x):x
    },
    //格式化时间,时间对象转yyyy-mm-dd hh:mm:ss
    formatTime(time){
      if(!time){
        return ''
      }
      let d=new Date(time);
      let tmpTime=d.getFullYear()+'-'+this.formatZero(d.getMonth()+1)+'-'+this.formatZero(d.getDate())+' '+this.formatZero(d.getHours())+':'+this.formatZero(d.getMinutes())+':'+this.formatZero(d.getSeconds());
      return tmpTime
    },



    test(){
      console.log(this.initData)
    },
  }
}
</script>

<style lang='scss' scoped>
.c-form{
  .el-form{
    display: flex;
    flex-wrap: wrap;
  }
}
</style>